// Copyright (C) 1953-2022 NUDT
// Verilog module name - time_extract
// Version: V4.1.0.20221206
// Created:
//         by - fenglin
////////////////////////////////////////////////////////////////////////////
// Description:
//         
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module time_extract
(
    i_clk  ,
    i_rst_n,
    
    i_sync_step_mode                      ,

    iv_data                               ,
	i_data_wr                             ,
    iv_sync_correctfield_time             ,
    iv_sync_link_delay                    ,
    
	//ov_cumulativescaledrateoffset         ,
	//o_cumulativescaledrateoffset_wr       ,
	
    ov_gm_timestamps                      ,
	ov_correctfield_time                  ,
	ov_local_cnt_rx                       ,
    ov_sync_correctfield_time             ,
    ov_sync_link_delay                    ,
	o_time_info_valid                      
);

// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n; 

input                   i_sync_step_mode;
// pkt input                      ;
input	   [8:0]	    iv_data        ;
input	         	    i_data_wr      ;
input      [63:0]	    iv_sync_correctfield_time             ;
input      [27:0]	    iv_sync_link_delay                    ;
// pkt output to NMA
//output reg [31:0]	    ov_cumulativescaledrateoffset        ;
//output reg	        o_cumulativescaledrateoffset_wr      ;

(*MARK_DEBUG="true"*)output reg [79:0]	    ov_gm_timestamps        ;
(*MARK_DEBUG="true"*)output reg [63:0]	    ov_correctfield_time    ;
(*MARK_DEBUG="true"*)output reg [39:0]	    ov_local_cnt_rx         ;
output reg [63:0]	    ov_sync_correctfield_time        ;
output reg [27:0]	    ov_sync_link_delay               ;  
(*MARK_DEBUG="true"*)output reg	            o_time_info_valid       ;     
//***************************************************
//        opensync correctionfield update
//***************************************************  
(*MARK_DEBUG="true"*)reg        [10:0]       rv_byte_cnt;
reg        [15:0]       rv_eth_type;
reg        [7:0]        rv_tsmp_type;
//reg        [7:0]        rv_tsmp_subtype;
(*MARK_DEBUG="true"*)reg        [2:0]        rv_tex_state;  
     
localparam              IDLE_S                          = 3'd0,
                        DISTINGUISH_PKT_S               = 3'd1,
						EXTRACT_ONESTEP_SYNC_INFO_S     = 3'd2, 
                        EXTRACT_TWOSTEP_SYNC_INFO_S     = 3'd3,
                        EXTRACT_TWOSTEP_FOLLOWUP_INFO_S = 3'd4,
                        DISCARD_PKT_S                   = 3'd5;                        
always @(posedge i_clk or negedge i_rst_n) begin
    if(i_rst_n == 1'b0)begin
        rv_byte_cnt                     <= 11'b0;
		
		//ov_cumulativescaledrateoffset    <= 32'h0;
		//o_cumulativescaledrateoffset_wr  <= 1'b0;
        rv_eth_type                      <= 16'b0;
        rv_tsmp_type                     <= 8'b0 ;
        //rv_tsmp_subtype                  <= 8'b0 ;

        ov_gm_timestamps                 <= 80'b0;
        ov_correctfield_time             <= 64'b0;
        ov_local_cnt_rx                  <= 40'b0;
        ov_sync_correctfield_time                  <= 64'b0;
        ov_sync_link_delay                         <= 28'b0; 
        o_time_info_valid                <= 1'b0 ;

        rv_tex_state                     <= IDLE_S;
    end
    else begin
        case(rv_tex_state)
            IDLE_S: begin				
				//ov_cumulativescaledrateoffset    <= 32'h0;
				//o_cumulativescaledrateoffset_wr  <= 1'b0;

				//ov_gm_timestamps                 <= 80'b0;
				//ov_correctfield_time             <= 64'b0;
				//ov_local_cnt_rx                  <= 24'b0;
				o_time_info_valid                <= 1'b0 ; 				
				if(i_data_wr)begin
					rv_byte_cnt  <= rv_byte_cnt + 1'b1;
					rv_tex_state <= DISTINGUISH_PKT_S;
			    end
				else begin
					rv_byte_cnt  <= 11'b0;
					rv_tex_state <= IDLE_S;
				end
			end
            DISTINGUISH_PKT_S:begin
				if(i_data_wr)begin
					rv_byte_cnt  <= rv_byte_cnt + 1'b1;
			    end
				else begin
					rv_byte_cnt  <= 11'b0;
				end

				if(rv_byte_cnt ==  11'd12)begin
                    rv_eth_type      <= {iv_data[7:0],8'b0};
                    rv_tsmp_type     <= 8'b0 ;
                    //rv_tsmp_subtype  <= 8'b0 ;
			    end
                else if(rv_byte_cnt ==  11'd13)begin
                    rv_eth_type      <= {rv_eth_type[15:8],iv_data[7:0]};
                    rv_tsmp_type     <= 8'b0 ;
                    //rv_tsmp_subtype  <= 8'b0 ;
			    end
                else if(rv_byte_cnt ==  11'd14)begin
                    rv_eth_type      <= rv_eth_type;
                    rv_tsmp_type     <= iv_data[7:0] ;
                    //rv_tsmp_subtype  <= 8'b0 ;
			    end
                else if(rv_byte_cnt ==  11'd15)begin
                    rv_eth_type      <= rv_eth_type  ;
                    rv_tsmp_type     <= rv_tsmp_type ;
                    //rv_tsmp_subtype  <= iv_data[7:0] ;
                    if((i_sync_step_mode == 1'b0) && (rv_eth_type == 16'hff01) && (rv_tsmp_type == 8'h06) && (iv_data[7:0] == 8'h01))begin//two_step,sync  
                        rv_tex_state     <= EXTRACT_TWOSTEP_SYNC_INFO_S;
                    end
                    else if((i_sync_step_mode == 1'b0) && (rv_eth_type == 16'hff01) && (rv_tsmp_type == 8'h06) && (iv_data[7:0] == 8'h07))begin//two_step,follow_up
                        rv_tex_state     <= EXTRACT_TWOSTEP_FOLLOWUP_INFO_S;
                    end
                    else if((i_sync_step_mode == 1'b1) && (rv_eth_type == 16'hff01) && (rv_tsmp_type == 8'h06) && (iv_data[7:0] == 8'h01))begin//one_step,sync
                        rv_tex_state     <= EXTRACT_ONESTEP_SYNC_INFO_S;
                    end                    
                    else begin
                        rv_tex_state     <= DISCARD_PKT_S;
                    end
			    end                 
				else begin
					rv_tex_state <= DISTINGUISH_PKT_S;
				end                                
            end
			EXTRACT_ONESTEP_SYNC_INFO_S:begin//local_cnt_rx,correctfield_time,gm_timestamps
				if(i_data_wr)begin
				   rv_byte_cnt            <= rv_byte_cnt + 1'b1;
				    rv_tex_state          <= EXTRACT_ONESTEP_SYNC_INFO_S;	
				end
				else begin
					rv_byte_cnt  <= 11'b0;
					rv_tex_state <= IDLE_S;				
				end
				
				if(rv_byte_cnt <= 11'd18)begin
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end
				else if(rv_byte_cnt <= 11'd23)begin//ov_local_cnt_rx
                    ov_local_cnt_rx <= {ov_local_cnt_rx[31:0],iv_data[7:0]}	;				
				end
				else if(rv_byte_cnt <= 11'd53)begin
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end
				else if(rv_byte_cnt <= 11'd61)begin//ov_correctfield_time
                    ov_correctfield_time <= {ov_correctfield_time[55:0],iv_data[7:0]}	;				
				end	
				else if(rv_byte_cnt <= 11'd79)begin
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end
				else if(rv_byte_cnt <= 11'd89)begin//gm_timestamps
                    ov_gm_timestamps <= {ov_gm_timestamps[71:0],iv_data[7:0]}	;				
				end	
				else if(rv_byte_cnt <= 11'd99)begin
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end
				else if(rv_byte_cnt <= 11'd103)begin//cumulativescaledrateoffset
                    //ov_cumulativescaledrateoffset <= {ov_cumulativescaledrateoffset[23:0],iv_data[7:0]}	;				
				end	
				else if(rv_byte_cnt == 11'd104)begin 
                    //o_cumulativescaledrateoffset_wr <= 1'b1	;
                    ov_sync_correctfield_time                  <= iv_sync_correctfield_time;
                    ov_sync_link_delay                         <= iv_sync_link_delay       ; 
                    o_time_info_valid               <= 1'b1 ;					
				end					
                else begin
                    //o_cumulativescaledrateoffset_wr <= 1'b0	;
                    o_time_info_valid               <= 1'b0 ;	
					
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					
                end 						
			
			end
            EXTRACT_TWOSTEP_SYNC_INFO_S:begin//local_cnt_rx
				o_time_info_valid         <= 1'b0 ;	
                if(i_data_wr)begin
				   rv_byte_cnt            <= rv_byte_cnt + 1'b1;
				    rv_tex_state          <= EXTRACT_TWOSTEP_SYNC_INFO_S;	
				end
				else begin
					rv_byte_cnt  <= 11'b0;
					rv_tex_state <= IDLE_S;				
				end
				
				if(rv_byte_cnt <= 11'd18)begin
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;
					//ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end
				else if(rv_byte_cnt <= 11'd23)begin//local_cnt_rx
                    ov_local_cnt_rx <= {ov_local_cnt_rx[31:0],iv_data[7:0]}	;				
				end
				//else if(rv_byte_cnt <= 11'd53)begin
				//    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;
					//ov_gm_timestamps      <= ov_gm_timestamps; 					 
				//end
				//else if(rv_byte_cnt <= 11'd61)begin//cumulativescaledrateoffset
                    //ov_correctfield_time <= {ov_correctfield_time[55:0],iv_data[7:0]}	;				
				//end	
				//else if(rv_byte_cnt <= 11'd79)begin
				//    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;
					//ov_gm_timestamps      <= ov_gm_timestamps; 					 
				//end
				//else if(rv_byte_cnt <= 11'd89)begin//cumulativescaledrateoffset
                //    ov_gm_timestamps <= {ov_gm_timestamps[71:0],iv_data[7:0]}	;				
				//end	
				//else if(rv_byte_cnt <= 11'd99)begin
				//    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;
					//ov_gm_timestamps      <= ov_gm_timestamps; 					 
				//end
				//else if(rv_byte_cnt <= 11'd103)begin//cumulativescaledrateoffset
				//    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;                    
                    //ov_cumulativescaledrateoffset <= {ov_cumulativescaledrateoffset[23:0],iv_data[7:0]}	;				
				//end	
				//else if(rv_byte_cnt == 11'd104)begin
				//    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;                  
                    //o_cumulativescaledrateoffset_wr <= 1'b1	;
                    //o_time_info_valid               <= 1'b0 ;					
				//end					
                else begin 
                    //o_cumulativescaledrateoffset_wr <= 1'b0	;
                    //o_time_info_valid               <= 1'b0 ;	
					
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;
					//ov_gm_timestamps      <= ov_gm_timestamps; 					
                end 						
			
			end
            EXTRACT_TWOSTEP_FOLLOWUP_INFO_S:begin//gm_timestamps
				if(i_data_wr)begin
				   rv_byte_cnt            <= rv_byte_cnt + 1'b1;
				    rv_tex_state          <= EXTRACT_TWOSTEP_FOLLOWUP_INFO_S;	
				end
				else begin
					rv_byte_cnt  <= 11'b0;
					rv_tex_state <= IDLE_S;				
				end
				/*
				if(rv_byte_cnt <= 11'd18)begin
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end
				else if(rv_byte_cnt <= 11'd21)begin//cumulativescaledrateoffset
                    ov_local_cnt_rx <= {ov_local_cnt_rx[15:0],iv_data[7:0]}	;				
				end
				else if(rv_byte_cnt <= 11'd53)begin
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end
				else if(rv_byte_cnt <= 11'd61)begin//cumulativescaledrateoffset
                    ov_correctfield_time <= {ov_correctfield_time[55:0],iv_data[7:0]}	;				
				end	
                */
				if(rv_byte_cnt <= 11'd53)begin
				    ov_local_cnt_rx       <= ov_local_cnt_rx;
				    ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end				
				else if(rv_byte_cnt <= 11'd61)begin//cumulativescaledrateoffset
                    ov_correctfield_time <= {ov_correctfield_time[55:0],iv_data[7:0]}	;				
				end	
				else if(rv_byte_cnt <= 11'd79)begin
				    //ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					 
				end
				else if(rv_byte_cnt <= 11'd89)begin//cumulativescaledrateoffset
                    ov_gm_timestamps <= {ov_gm_timestamps[71:0],iv_data[7:0]}	;				
				end	
				//else if(rv_byte_cnt <= 11'd99)begin
				    //ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;
				//	ov_gm_timestamps      <= ov_gm_timestamps; 					 
				//end
				else if(rv_byte_cnt <= 11'd103)begin//cumulativescaledrateoffset
                    //ov_cumulativescaledrateoffset <= {ov_cumulativescaledrateoffset[23:0],iv_data[7:0]}	;
                    ov_gm_timestamps      <= ov_gm_timestamps;                    
				end	
				else if(rv_byte_cnt == 11'd104)begin 
                    //o_cumulativescaledrateoffset_wr <= 1'b1	;
                    ov_sync_correctfield_time                  <= iv_sync_correctfield_time;
                    ov_sync_link_delay                         <= iv_sync_link_delay       ; 
                    o_time_info_valid               <= 1'b1 ;					
				end					
                else begin
                    //o_cumulativescaledrateoffset_wr <= 1'b0	;
                    o_time_info_valid               <= 1'b0 ;	
					
				    //ov_local_cnt_rx       <= ov_local_cnt_rx;
				    //ov_correctfield_time  <= ov_correctfield_time;
					ov_gm_timestamps      <= ov_gm_timestamps; 					
                end 						
			
			end            
            DISCARD_PKT_S:begin
				o_time_info_valid                <= 1'b0 ;
				if(i_data_wr)begin
				    rv_tex_state          <= DISCARD_PKT_S;	
				end
				else begin
					rv_tex_state <= IDLE_S;				
				end
            end            
            default:begin
				//o_cumulativescaledrateoffset_wr <= 1'b0	;
				o_time_info_valid               <= 1'b0 ;	
				
                rv_tex_state                    <= IDLE_S;
            end
        endcase
    end
end
endmodule